using System;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Text;
using NCommet.Core;
using System.Xml;
using NCommet.Core.Agents;
using System.Collections.ObjectModel;
using System.Collections;
using System.Configuration;

namespace NCommet.Modules.TypedTreeValidatorTest
{
    /// <summary>
    /// A sample implementation of <see cref="NCommet.Core.Agents.ITypedTreeValidator"/>. The rules are based on item types contained as constants in the <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes"/> class and on content objects instantianted from the content classes of the <see cref="NCommet.Modules.TypedTreeValidatorTest"/> namespace.
    /// </summary>
    public class BlogsTTV : ITypedTreeValidator
    {

        #region ITypedTreeValidator Members

        /// <summary>
        /// Checks if the item can be set as root.
        /// </summary>
        /// <param name="CandidateRoot">The item that is checked.</param>
        /// <returns>True, if the item is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.BLOG"/>.</returns>
        public bool CanSetRoot(Item CandidateRoot)
        {
            ICollection<string> ValidationSummary;
            return CanSetRoot(CandidateRoot, out ValidationSummary);
        }

        /// <summary>
        /// Checks if the item can be set as root.
        /// If the operation is not allowed, validation errors will be returned in <paramref name="ValidationSummary"/>.
        /// </summary>
        /// <param name="CandidateRoot">The item that is checked.</param>
        /// <param name="ValidationSummary">The validation errors returned.</param>
        /// <returns>True, if the item is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.BLOG"/>.</returns>
        public bool CanSetRoot(Item CandidateRoot, out ICollection<string> ValidationSummary)
        {
            ValidationSummary = null;
            if (CandidateRoot.ItemType == ItemTypes.BLOG)
            {
                return true;
            }
            else
            {
                ValidationSummary = new List<string>();
                ValidationSummary.Add("Cannot set " + CandidateRoot.ItemType + " as root");
                return false;
            }
        }

        /// <summary>
        /// Checks if <paramref name="CandidateChild"/> can be attached as a child of <paramref name="Parent"/>.
        /// </summary>
        /// <param name="Parent">The parent item.</param>
        /// <param name="CandidateChild">The candidate child item.</param>
        /// <returns>
        ///     <para>True, only for the following conditions:</para>
        ///     <para><list type="bullet">
        ///         <item><description><paramref name="Parent"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.BLOG"/> and <paramref name="CandidateChild"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.POST"/>.</description></item>
        ///         <item><description><paramref name="Parent"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.POST"/> and <paramref name="CandidateChild"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.COMMENT"/>.</description></item>
        ///     </list></para>
        /// </returns>
        public bool CanAttach(Item Parent, Item CandidateChild)
        {
            ICollection<string> ErrorMessages;
            return CanAttach(Parent, CandidateChild, out ErrorMessages);
        }

        /// <summary>
        /// Checks if <paramref name="CandidateChild"/> can be attached as a child of <paramref name="Parent"/>
        /// If the operation is not allowed, validation errors will be returned in <paramref name="ValidationSummary"/>
        /// </summary>
        /// <param name="Parent">The parent item.</param>
        /// <param name="CandidateChild">The candidate child item.</param>
        /// <param name="ValidationSummary">The validation errors returned.</param>
        /// <returns>
        ///     <para>True, only for the following conditions:</para>
        ///     <para><list type="bullet">
        ///         <item><description><paramref name="Parent"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.BLOG"/> and <paramref name="CandidateChild"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.POST"/>.</description></item>
        ///         <item><description><paramref name="Parent"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.POST"/> and <paramref name="CandidateChild"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.COMMENT"/>.</description></item>
        ///     </list></para>
        /// </returns>
        public bool CanAttach(Item Parent, Item CandidateChild, out ICollection<string> ValidationSummary)
        {
            ValidationSummary = null;
            if (
                (Parent.ItemType == ItemTypes.BLOG && CandidateChild.ItemType == ItemTypes.POST) ||
                (Parent.ItemType == ItemTypes.POST && CandidateChild.ItemType == ItemTypes.COMMENT))
                return true;

            else
            {
                ValidationSummary = new List<string>();
                ValidationSummary.Add("Cannot attach " + CandidateChild.ItemType + " to " + Parent.ItemType);
                return false;
            }
        }

        /// <summary>
        /// Checks if <paramref name="Child"/> can be removed from its parent.
        /// </summary>
        /// <param name="Parent">The parent item.</param>
        /// <param name="Child">The child item.</param>
        /// <returns>True always.</returns>
        public bool CanRemove(Item Parent, Item Child)
        {
            return true;
        }

        /// <summary>
        /// Checks if <paramref name="Child"/> can be removed from its parent.
        /// If the operation is not allowed, validation errors will be returned in <paramref name="ValidationSummary"/>
        /// </summary>
        /// <param name="Parent">The parent item.</param>
        /// <param name="Child">The child item.</param>
        /// <param name="ValidationSummary">The validation errors returned.</param>
        /// <returns>True always.</returns>
        public bool CanRemove(Item Parent, Item Child, out ICollection<string> ValidationSummary)
        {
            ValidationSummary = null;
            return true;
        }

        /// <summary>
        /// Checks if <paramref name="Container"/> can contain <paramref name="CandidateContent"/> as its content.
        /// </summary>
        /// <param name="Container">The container item.</param>
        /// <param name="CandidateContent">The candidate content.</param>
        /// <returns>
        ///     <para>True, only for the following conditions:</para>
        ///     <para><list type="bullet">
        ///         <item><description><paramref name="Container"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.BLOG"/> and <paramref name="CandidateContent"/> is an instance of <see cref="NCommet.Modules.TypedTreeValidatorTest.Blog"/>.</description></item>
        ///         <item><description><paramref name="Container"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.POST"/> and <paramref name="CandidateContent"/> is an instance of <see cref="NCommet.Modules.TypedTreeValidatorTest.NewsPost"/>.</description></item>
        ///         <item><description><paramref name="Container"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.POST"/> and <paramref name="CandidateContent"/> is an instance of <see cref="NCommet.Modules.TypedTreeValidatorTest.SportsPost"/>.</description></item>
        ///         <item><description><paramref name="Container"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.COMMENT"/> and <paramref name="CandidateContent"/> is an instance of <see cref="NCommet.Modules.TypedTreeValidatorTest.Comment"/>.</description></item>
        ///     </list></para>
        /// </returns>
        public bool CanContain(Item Container, ContentBase CandidateContent)
        {
            ICollection<string> ErrorMessages;
            return CanContain(Container, CandidateContent, out ErrorMessages);
        }

        /// <summary>
        /// Checks if <paramref name="Container"/> can contain <paramref name="CandidateContent"/> as its content.
        /// If the operation is not allowed, validation errors will be returned in <paramref name="ValidationSummary"/>
        /// </summary>
        /// <param name="Container">The container item.</param>
        /// <param name="CandidateContent">The candidate content.</param>
        /// <param name="ValidationSummary">The validation errors returned.</param>
        /// <returns>
        ///     <para>True, only for the following conditions:</para>
        ///     <para><list type="bullet">
        ///         <item><description><paramref name="Container"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.BLOG"/> and <paramref name="CandidateContent"/> is an instance of <see cref="NCommet.Modules.TypedTreeValidatorTest.Blog"/>.</description></item>
        ///         <item><description><paramref name="Container"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.POST"/> and <paramref name="CandidateContent"/> is an instance of <see cref="NCommet.Modules.TypedTreeValidatorTest.NewsPost"/>.</description></item>
        ///         <item><description><paramref name="Container"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.POST"/> and <paramref name="CandidateContent"/> is an instance of <see cref="NCommet.Modules.TypedTreeValidatorTest.SportsPost"/>.</description></item>
        ///         <item><description><paramref name="Container"/> is of type <see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.COMMENT"/> and <paramref name="CandidateContent"/> is an instance of <see cref="NCommet.Modules.TypedTreeValidatorTest.Comment"/>.</description></item>
        ///     </list></para>
        /// </returns>
        public bool CanContain(Item Container, ContentBase CandidateContent, out ICollection<string> ValidationSummary)
        {
            ValidationSummary = null;
            if (
                (Container.ItemType == ItemTypes.BLOG && CandidateContent is Blog) ||
                (Container.ItemType == ItemTypes.POST && CandidateContent is NewsPost) ||
                (Container.ItemType == ItemTypes.POST && CandidateContent is SportsPost) ||
                (Container.ItemType == ItemTypes.COMMENT && CandidateContent is Comment))
                return true;
            else
            {
                ValidationSummary = new List<string>();
                ValidationSummary.Add(Container.ItemType + " cannot contain type " + CandidateContent.GetType().FullName);
                return false;
            }
        }

        /// <summary>
        /// Gets the valid child item types for the given item.
        /// </summary>
        /// <param name="Parent">The given parent item.</param>
        /// <returns>
        ///     <para>Returns the following valid child item types for the given <paramref name="Parent"/>:</para>
        ///     <para><list type="table">
        ///         <listheader>
        ///             <term>Item type of <paramref name="Parent"/></term>
        ///             <term>Item types of valid children</term>
        ///         </listheader>
        ///         <item>
        ///             <description><see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.BLOG"/></description>
        ///             <description>
        ///                 <list type="bullet">
        ///                     <item><description><see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.POST"/></description></item>
        ///                 </list>
        ///             </description>
        ///         </item>
        ///         <item>
        ///             <description><see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.POST"/></description>
        ///             <description>
        ///                 <list type="bullet">
        ///                     <item><description><see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.COMMENT"/></description></item>
        ///                 </list>
        ///             </description>
        ///         </item>
        ///     </list></para>
        /// </returns>
        public System.Collections.Generic.ICollection<string> GetValidChildItemTypes(Item Parent)
        {
            if (Parent.ItemType == ItemTypes.BLOG)
                return ToCol(ItemTypes.POST);
            else if (Parent.ItemType == ItemTypes.POST)
                return ToCol(ItemTypes.COMMENT);
            else
                return new List<string>();
        }

        /// <summary>
        /// Gets the valid content types for the given item.
        /// Content types are returned as fully qualified type names.
        /// </summary>
        /// <param name="Container">The given item.</param>
        /// <returns>
        ///     <para>Returns the fully qualified type name of the following valid content types for the given <paramref name="Container"/>:</para>
        ///     <para><list type="table">
        ///         <listheader>
        ///             <term>Item type of <paramref name="Container"/></term>
        ///             <term>Valid content types</term>
        ///         </listheader>
        ///         <item>
        ///             <description><see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.BLOG"/></description>
        ///             <description>
        ///                 <list type="bullet">
        ///                     <item><description><see cref="NCommet.Modules.TypedTreeValidatorTest.Blog"/></description></item>
        ///                 </list>
        ///             </description>
        ///         </item>
        ///         <item>
        ///             <description><see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.POST"/></description>
        ///             <description>
        ///                 <list type="bullet">
        ///                     <item><description><see cref="NCommet.Modules.TypedTreeValidatorTest.NewsPost"/></description></item>
        ///                     <item><description><see cref="NCommet.Modules.TypedTreeValidatorTest.SportsPost"/></description></item>
        ///                 </list>
        ///             </description>
        ///         </item>
        ///         <item>
        ///             <description><see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.COMMENT"/></description>
        ///             <description>
        ///                 <list type="bullet">
        ///                     <item><description><see cref="NCommet.Modules.TypedTreeValidatorTest.Comment"/></description></item>
        ///                 </list>
        ///             </description>
        ///         </item>
        ///     </list></para>
        /// </returns>
        public System.Collections.Generic.ICollection<string> GetValidContentTypes(Item Container)
        {

            switch (Container.ItemType)
            {
                case ItemTypes.BLOG:
                    return ToCol(typeof(Blog).AssemblyQualifiedName);
                case ItemTypes.POST:
                    List<string> result = new List<string>();
                    result.Add(typeof(NewsPost).AssemblyQualifiedName);
                    result.Add(typeof(SportsPost).AssemblyQualifiedName);
                    return result;
                case ItemTypes.COMMENT:
                    return ToCol(typeof(Comment).AssemblyQualifiedName);
                default:
                    return null;
            }
        }

        /// <summary>
        /// Gets the valid item types for a root item.
        /// </summary>
        /// <returns>A collection of the valid item types for a root item.</returns>
        /// <returns>
        ///     <para>Returns the following valid child item types for a root item:</para>
        ///     <para><list type="bullet">
        ///           <item><description><see cref="NCommet.Modules.TypedTreeValidatorTest.ItemTypes.BLOG"/></description></item>
        ///     </list></para>
        /// </returns>
        public System.Collections.Generic.ICollection<string> GetValidRootItemTypes()
        {
            return ToCol(ItemTypes.BLOG);
        }
        #endregion

        #region Helper methods

        private static ICollection<string> ToCol(string oneItem)
        {
            List<string> result = new List<string>();
            result.Add(oneItem);
            return result;
        }

        #endregion

    }
}
